import React, { Component } from 'react';
import PropTypes from 'prop-types';
import { NavLink } from 'react-router-dom';
import {
  getTasksList,
  batchDeleteTasks,
  restartTask,
  stopTask,
  updateTaskCycle,
  cancelTask,
  resumeTask
} from '@api/task';
import {
  Radio,
  Button,
  Switch,
  Progress,
  Input,
  Table,
  Select,
  Modal,
  message,
  ConfigProvider,
  Empty,
  Popover,
  Icon,
  Tooltip
} from 'antd';
import OnedayModal from './components/oneday-modal';
import ZoomeyeModal from './components/zoomeye-modal';
import moment from 'moment';
import { loadAssets } from '@api/asset';
import _ from 'lodash';
import {
  WAITING_TASK_STATES,
  PROCESSING_TASK_STATES,
  FINISHED_TASK_STATES,
  TASK_TYPE_MAP
} from '@util/constants';
import { connect } from 'react-redux';
import Operator from './components/operator';
import getElapsed from '@util/get-elapsed';
import getRealTime from '@util/get-real-time';
import EmptyDataImg from '@images/empty-data.svg';
import TaskExportModal from '../components/task-export-modal';
import './index.less';
import { actions as systemActions } from '@redux/reducer/system';
import { bindActionCreators } from 'redux';
import { withRouter } from 'react-router-dom';
import isClusterModel from '@components/is-cluster-model';
const { Group: RadioGroup, Button: RadioButton } = Radio;
const Search = Input.Search;
const SelectOption = Select.Option;

const moreTypesMap = {
  stop: '终止',
  delete: '删除',
  cancel: '取消',
  batchDelete: '批量删除',
  reDetect: '复测',
  start: '启动',
  paused: '暂停',
  resume: '启动'
};

const statusTextMap = {
  readying: '准备中',
  waiting: '未开始',
  end: '已完成',
  running: '运行中',
  paused: '已暂停'
};
class TaskManageList extends Component {
  constructor(props) {
    super(props);
    const taskFilterString = sessionStorage.getItem('filter_taskListFilter');
    let taskFilter;
    try {
      taskFilter = JSON.parse(taskFilterString);
    } catch (error) {
      taskFilter = {};
    }

    this.state = {
      taskFilter: {
        page: 1,
        pageSize: 10,
        status: 'processing',
        scanType: 'all',
        search: '',
        isCycle: '',
        ...taskFilter
      },
      templateIps: [],
      tasks: [],
      taskIds: [],
      selectedRowKeys: [],
      loadingTasks: false,
      totalTasksCount: 0,
      onedayModalVisible: false,
      zoomeyeModalVisible: false,
      moreModalType: '',
      moreModalLoading: false,

      currentTask: {},
      differenceTime: '',
      systeTimeNow: '',
      nowDate: new Date().getTime()
    };
  }

  componentDidMount() {
    this.bindSocketIO();
    this.loadTasks();
    // this.props.getServerTime();
    this.getLoactiontime();
    // this.loadTemplateAssets();
  }
  // 耗时使用本地系统时间即可，无需使用系统时间
  getLoactiontime = () => {
    this.timer = window.setInterval(() => {
      this.setState({ nowDate: new Date().getTime() });
    }, 1000);
  };
  loadTemplateAssets = () => {
    loadAssets({
      page: 1,
      pageSize: 7,
      mode: 'list'
    }).then(res => {
      const assets = _.get(res, 'data.data.list', []);
      let templateIps = assets.map(asset => asset.ip);
      if (templateIps.length === 7) {
        templateIps = templateIps.slice(0, 5).concat('...');
      }
      this.setState({
        templateIps
      });
    });
  };

  componentWillUnmount() {
    if (this.timer) {
      window.clearInterval(this.timer);
      this.timer = null;
    }
    this.unbindSocketIO();
  }

  hitTaskFilter = data => {
    const { taskIds } = this.state;
    const { taskId } = data;
    return taskIds.indexOf(taskId) !== -1;
  };

  bindSocketIO = () => {
    const { socketIO } = this.props;
    if (!socketIO) {
      return;
    }
    socketIO.on('task_handler', this.onSocketIOData, this.hitTaskFilter);
  };

  unbindSocketIO = () => {
    const { socketIO } = this.props;
    if (!socketIO) {
      return;
    }
    socketIO.cancel('task_handler', this.onSocketIOData);
  };

  onSocketIOData = data => {
    const { type } = data;
    switch (type) {
      case 'TASK_DELETED':
        message.error('该任务已被删除');
        this.loadTasks();
        break;
      case 'task_running':
      case 'task_stopped':
      case 'task_failed':
      case 'task_paused':
      case 'UPDATE_TASK_STATUS':
        this.loadTasks();
        break;
      case 'UPDATE_ENGINE_PROGRESS':
        this.onSocketIODataEngine(data);
        break;
      case 'UPDATE_TASK_PROGRESS':
        this.onSocketIODataProcess(data);
        break;

      default:
        break;
    }
  };
  onSocketIODataEngine = data => {
    const { taskId, engineProgress } = data;
    const { tasks } = this.state;
    const newTasks = tasks.map(task => {
      if (task._id === taskId) {
        task.progress.engineProgress = engineProgress;
        task.status = 'processing';
      }
      return task;
    });
    this.setState({ tasks: newTasks });
  };

  onSocketIODataProcess = data => {
    const { taskId, progress } = data;
    const { tasks } = this.state;
    const newTasks = tasks.map(task => {
      if (task._id === taskId) {
        task.progress.progress = progress;
        task.status = 'processing';
      }
      return task;
    });
    this.setState({ tasks: newTasks });
  };

  loadTasks = () => {
    const taskFilter = _.clone(this.state.taskFilter);
    const originStatus = taskFilter.status;
    sessionStorage.setItem('filter_taskListFilter', JSON.stringify(taskFilter));
    for (let key in taskFilter) {
      if (!taskFilter[key] && (key !== 'isCycle' || taskFilter[key] === '')) {
        delete taskFilter[key];
      }
    }
    if (taskFilter.status === 'waiting') {
      taskFilter.status = WAITING_TASK_STATES;
      delete taskFilter['isCycle'];
    } else if (taskFilter.status === 'finished') {
      taskFilter.status = FINISHED_TASK_STATES;
    } else {
      taskFilter.status = PROCESSING_TASK_STATES;
      delete taskFilter['isCycle'];
    }
    if (taskFilter.scanType === 'all') {
      delete taskFilter.scanType;
    }

    this.setState({
      loadingTasks: true,
      tasks: []
    });
    getTasksList(taskFilter)
      .then(res => {
        const currentStatus = _.get(this.state, 'taskFilter.status');
        if (currentStatus && originStatus !== currentStatus) {
          return;
        }
        const result = _.get(res, 'data.result');
        if (result) {
          const { list: tasks = [], count: totalTasksCount = 0 } = _.get(res, 'data.data', {});
          const taskIds = tasks.map(task => {
            const taskId = task._id;
            if (task.scope === 'all' && task.scanType === 'OneDay') {
              // eslint-disable-next-line
              task.site_oids = [{ ip: '全部资产' }];
            }
            if (task.scope === 'all' && task.scanType === 'Web') {
              task.ips = ['全部资产'];
            }
            return taskId;
          });
          this.setState({
            tasks,
            taskIds,
            totalTasksCount
          });
        }
      })
      .catch(error => {
        window.console.log(error);
      })
      .finally(() => {
        this.setState({
          loadingTasks: false
        });
      });
  };

  deleteTasks = ids => {
    const { selectedRowKeys } = this.state;
    this.setState({ moreModalLoading: true });
    batchDeleteTasks({
      // eslint-disable-next-line
      task_ids: ids
    })
      .then(() => {
        message.success('任务开始删除');
        this.setState({
          moreModalType: '',
          currentTask: {},
          selectedRowKeys: _.difference(selectedRowKeys, ids)
        });
        this.loadTasks();
      })
      .catch(({ message: msg }) => {
        if (msg === 'demonstrate forbidden') {
          message.info('演示版本不能删除任务，请联系ZoomEye BE团队获取正式版本');
        } else {
          message.error('删除任务失败');
        }
      })
      .finally(() => {
        this.setState({ moreModalLoading: false });
      });
  };

  setAddTaskModalVisible = (type, visible) => {
    this.setState({
      [`${type}ModalVisible`]: visible
    });
  };

  wrapOnFilterChange = (key, path) => value => {
    const taskFilter = _.clone(this.state.taskFilter);
    taskFilter[key] = path ? _.get(value, path) : value;
    taskFilter.page = 1;
    this.setState(
      {
        taskFilter
      },
      this.loadTasks
    );
  };

  onTableChange = ({ current: page, pageSize }, filters) => {
    document.getElementsByClassName('ant-layout-content')[0].scrollTop = 0;
    const taskFilter = this.state.taskFilter;
    this.setState(
      {
        taskFilter: {
          ...taskFilter,
          page,
          pageSize,
          isCycle: _.get(filters, 'create-duty[0]', '')
        }
      },
      this.loadTasks
    );
  };

  scorllToTop = () => {
    document.documentElement.scrollTop = 0;
  };

  wrapSwitchCycle = row => checked => {
    updateTaskCycle({
      taskId: row._id,
      isCycle: checked,
      actionDesc: checked ? '开启' : '关闭'
    })
      .then(() => {
        message.success('修改周期任务成功');
        this.loadTasks();
      })
      .catch(() => {
        message.error('修改周期任务失败');
      });
  };

  getPauseTime = (lastResumed, pendingTime) => {
    const { systeTimeNow } = this.state;
    if (systeTimeNow && lastResumed && pendingTime) {
      return getElapsed(
        moment(lastResumed).add(pendingTime, 'milliseconds'),
        systeTimeNow.format('YYYY-MM-DD HH:mm:ss')
      );
    }
    return '';
  };

  getProgress = row => {
    const { status } = row;
    if (status === 'stopping') {
      return '-';
    } else {
      const { lastResumed, scanType, status, pendingTime, lastStart } = row;
      const engineProgress = _.get(row, 'progress.engineProgress', []);

      const kmap = _.find(engineProgress, { name: 'kmap' }) || {};
      const xmap = _.find(engineProgress, { name: 'xmap' }) || {};
      const wmap = _.find(engineProgress, { name: 'wmap' }) || {};
      const pocsuite3 = _.find(engineProgress, { name: 'pocsuite3' }) || {};
      const nuclei = _.find(engineProgress, { name: 'nuclei' }) || {};
      const nscan = _.find(engineProgress, { name: 'nscan' }) || {};

      let popoverDesc = [];
      if (scanType !== 'OneDay') {
        popoverDesc.push({ ...kmap, name: '存活探测引擎' }, { ...xmap, name: '资产探测引擎' });

        if (
          _.get(
            row,
            `${
              scanType === 'Zoomeye' ? 'maxDetectionTaskParams' : 'onedayTaskParams'
            }.webFingerprintDetection`,
            false
          )
        ) {
          popoverDesc.push({ ...wmap, name: 'Web探测引擎' });
        }
      }
      if (scanType !== 'Zoomeye') {
        let nucleiDist = {};
        let pocsuite3Dist = {};
        let nscanDist = {};
        [nuclei, pocsuite3, nscan].forEach(r => {
          if (r) {
            let dist = {};
            Object.keys(r).forEach(i => {
              dist[`${i}_${r.name}`] = r[i];
            });
            if (r.name === 'pocsuite3') {
              pocsuite3Dist = { ...dist };
            } else if (r.name === 'nscan') {
              nscanDist = { ...dist };
            } else {
              nucleiDist = { ...dist };
            }
          }
        });
        popoverDesc.push({ ...pocsuite3Dist, name: '漏洞检测引擎', ...nucleiDist, ...nscanDist });
      }
      //  仅端口存活只有kmap
      if (
        _.get(row, 'maxDetectionTaskParams.portDetectionOnly', false) ||
        _.get(row, 'onedayTaskParams.portDetectionOnly', false)
      ) {
        popoverDesc = [{ ...kmap, name: '存活探测引擎' }];
      }
      const progress = _.get(row, 'progress.progress', 0);
      const strokeColor = status === 'paused' ? '#F8954A' : '#1890FF';
      const successFuc = desc => {
        let sum = _.get(desc, 'success', 0) + _.get(desc, 'failure', 0);
        if (desc.success_nuclei) {
          sum += desc.success_nuclei + _.get(desc, 'failure_nuclei', 0);
        }
        if (desc.success_nscan) {
          sum += desc.success_nscan + _.get(desc, 'failure_nscan', 0);
        }
        if (desc.success_pocsuite3) {
          sum += desc.success_pocsuite3 + _.get(desc, 'failure_pocsuite3', 0);
        }
        return sum;
      };
      const totalFuc = desc => {
        let sum = _.get(desc, 'total', 0) + _.get(desc, 'failure', 0);
        if (desc.total_nuclei) {
          sum += desc.total_nuclei + _.get(desc, 'failure_nuclei', 0);
        }
        if (desc.total_nscan) {
          sum += desc.total_nscan + _.get(desc, 'failure_nscan', 0);
        }
        if (desc.total_pocsuite3) {
          sum += desc.total_pocsuite3 + _.get(desc, 'failure_pocsuite3', 0);
        }
        return sum;
      };
      const getStatus = desc => {
        if (desc.status) {
          return statusTextMap[desc.status] ? statusTextMap[desc.status] : '未开始';
        }
        function filterStatus() {
          let statusList = [];
          Object.keys(desc).find(r => {
            ['status_nscan', 'status_nuclei', 'status_pocsuite3'].includes(r)
              ? statusList.push(desc[r])
              : null;
          });
          if (statusList.every((element, index, self) => element === self[0])) {
            return statusList[0];
          } else if (statusList.find(r => r === 'running')) {
            return 'running';
          }
          return 'waiting';
        }
        return statusTextMap[filterStatus()];
      };
      return (
        <Popover
          content={popoverDesc.map(desc => {
            return (
              <div key={desc.name}>
                {desc.name}
                {successFuc(desc)}/{totalFuc(desc)}:{getStatus(desc)}
                {/* {statusTextMap[desc.status] ? statusTextMap[desc.status] : '未开始'} */}
              </div>
            );
          })}
        >
          <div className="process">
            <p className="num">{progress}%</p>
            <Progress
              style={{ maxWidth: '250px' }}
              percent={progress}
              strokeColor={strokeColor}
              showInfo={false}
            />
            {status === 'paused' || status === 'finished' || status === 'fail' ? (
              <p className="spend">
                {status === 'paused' && '已暂停: '}已耗时
                {getRealTime(lastStart, this.state.nowDate, pendingTime, 'paused')}
              </p>
            ) : (
              <p className="spend">
                已耗时:
                {pendingTime !== 0
                  ? getRealTime(lastStart, this.state.nowDate, pendingTime, lastResumed)
                  : getRealTime(lastStart, this.state.nowDate, pendingTime, 'undone')}
              </p>
            )}
          </div>
        </Popover>
      );
    }
  };

  getColumns = () => {
    const taskFilter = this.state.taskFilter;
    const { modules = [] } = this.props;
    const hasOneDayModule = modules.includes('1day');
    let hookColumns = [];

    if (taskFilter.status === 'processing') {
      hookColumns = [
        {
          title: '开始时间',
          dataIndex: 'lastStart',
          render: (time, { status } = {}) =>
            status !== 'stopping' ? moment(time).format('YYYY-MM-DD HH:mm') : '-'
        },
        {
          title: '进度',
          key: 'progress',
          render: row => this.getProgress(row)
        }
      ];
    } else if (taskFilter.status === 'finished') {
      hookColumns = [
        {
          title: (
            <span>
              结果&nbsp;
              <Popover
                content={
                  <span>
                    {hasOneDayModule && '漏洞普查：最后一轮检测出的漏洞数'}
                    {hasOneDayModule && <br />}
                    资产探测：最后一轮探测存活的目标数
                    <br />
                    {hasOneDayModule && '1DAY任务：最后一轮检测出的漏洞数'}
                    {hasOneDayModule && <br />}
                    {hasOneDayModule && '弱口令任务：最后一轮检测出的漏洞数'}
                  </span>
                }
              >
                <Icon type="exclamation-circle" style={{ cursor: 'pointer' }} />
              </Popover>
            </span>
          ),
          key: 'result',
          render: row => {
            const isFail = _.get(row, 'status', '') === 'fail';
            const scanType = _.get(row, 'scanType', '');
            const isAbnormal = _.get(row, 'isAbnormal', false);
            const failMsg = _.get(row, 'failMessage') || '-';
            let popContent = (
              <div>
                <div>
                  {isFail && `${TASK_TYPE_MAP[scanType]}任务失败，扫描结果可能不完全。\n`}
                  {isFail && isAbnormal && <br />}
                  {isAbnormal && '该轮探测与历史相比变化较大，可能为异常数据。'}
                </div>
                <div>失败原因：&quot;{failMsg}&quot;</div>
              </div>
            );
            const scannedCount = _.get(row, 'latestResultCount', '-');
            return (
              <span className={`result ${(isFail || isAbnormal) && 'result-red'}`}>
                {scannedCount}
                &nbsp;
                {(isFail || isAbnormal) && (
                  <Popover content={popContent}>
                    <Icon type="exclamation-circle" style={{ cursor: 'pointer' }} />
                  </Popover>
                )}
              </span>
            );
          }
        },
        {
          title: '时间',
          key: 'spend',
          width: 300,
          render: row => {
            const { lastStart, lastEnd, pendingTime } = row;
            const time = (
              <div className="time">
                <p>
                  最近一轮开始时间:
                  <br />
                  {lastStart ? moment(lastStart).format('YYYY-MM-DD HH:mm:ss') : '-'}
                </p>
                <p>
                  最近一轮终检时间:
                  <br />
                  {lastEnd ? moment(lastEnd).format('YYYY-MM-DD HH:mm:ss') : '-'}
                </p>
                <p className="spend">
                  耗时: {getRealTime(lastStart, lastEnd, pendingTime, 'done')}
                </p>
              </div>
            );
            return time;
          }
        },
        {
          title: '下轮开始时间',
          key: 'next',
          render: row => {
            let { scanType, lastEnd, timing, status } = row;
            let intervalTime, recentEndTime, isCycle, intervalUnit;
            if (
              scanType === 'Zoomeye' ||
              scanType === 'Web' ||
              scanType === 'Honeypot' ||
              scanType === 'VulDetect'
            ) {
              isCycle = _.get(row, 'isCycle', false);
              intervalTime = _.get(row, 'intervalTime');
              intervalUnit = _.get(row, 'intervalUnit');
              recentEndTime = !['processing', 'paused', 'stopped'].includes(status) && lastEnd;
            }
            const endAt = _.get(timing, 'endAt');
            const dailyEnd = _.get(timing, 'dailyEnd');
            const dailyStart = _.get(timing, 'dailyStart');
            const momentIntervalTime = moment(lastEnd)
              .add(intervalTime, intervalUnit)
              .format('YYYY-MM-DD HH:mm:ss');

            const isBetween = (dailyStart, dailyEnd, intervalTime) => {
              let dailyStartDate = new Date(moment(intervalTime));
              dailyStartDate.setHours(dailyStart.split(':')[0]);
              dailyStartDate.setMinutes(dailyStart.split(':')[1]);
              let dailyEndDate = new Date(moment(intervalTime));
              dailyEndDate.setHours(dailyEnd.split(':')[0]);
              dailyEndDate.setMinutes(dailyEnd.split(':')[1]);
              if (
                moment(moment(intervalTime).format('YYYY-MM-DD HH:mm')).isBetween(
                  moment(dailyStartDate).format('YYYY-MM-DD HH:mm'),
                  moment(dailyEndDate).format('YYYY-MM-DD HH:mm')
                )
              ) {
                return true;
              }
              return false;
            };

            const InspectionTime = () => {
              if (endAt || dailyEnd) {
                if (momentIntervalTime < moment(endAt).format('YYYY-MM-DD HH:mm:ss')) {
                  if (dailyStart && dailyEnd) {
                    return isBetween(dailyStart, dailyEnd, momentIntervalTime);
                  }
                  return true;
                }
                if (dailyStart && dailyEnd) {
                  return isBetween(dailyStart, dailyEnd, momentIntervalTime);
                }
                return false;
              }
              return true;
            };
            if (
              isCycle &&
              lastEnd &&
              intervalTime &&
              intervalUnit &&
              recentEndTime &&
              !['paused', 'stopped'].includes(status) &&
              InspectionTime()
            ) {
              return moment(lastEnd)
                .add(intervalUnit, intervalTime)
                .format('YYYY-MM-DD HH:mm:ss');
            } else {
              return <Popover content="无任务周期">-</Popover>;
            }
          }
        },
        {
          title: '创建周期',
          key: 'create-duty',
          filters: [{ text: '有周期', value: true }, { text: '无周期', value: false }],
          filterMultiple: false,
          filteredValue:
            this.state.taskFilter.isCycle === '' ? [] : [this.state.taskFilter.isCycle],
          render: row => {
            let { scanType } = row;
            let isCycle = false;
            if (['Zoomeye', 'VulDetect'].includes(scanType)) {
              isCycle = _.get(row, 'isCycle', false);
            }
            const cycle = !isCycle ? (
              <Popover content="受任务执行时限、每日允许时间段限制，该任务已不能再执行新的任务。">
                <Switch
                  className="cycle"
                  checked={isCycle}
                  disabled={!isCycle}
                  onClick={isCycle && this.wrapSwitchCycle(row)}
                />
              </Popover>
            ) : (
              <Switch
                className="cycle"
                checked={isCycle}
                disabled={!isCycle}
                onClick={isCycle && this.wrapSwitchCycle(row)}
              />
            );
            return cycle;
          }
        }
      ];
    }

    const columns = [
      {
        title: '任务名称',
        width: 150,
        className: 'task-name',
        render: item => {
          const name = _.get(item, 'name', '-');
          const urgent = _.get(item, 'urgent', false);
          let { scanType, _id } = item;
          let detailUrl = '';
          if (scanType === 'Zoomeye') {
            detailUrl = `/task-manage/zoomeye-detail/${_id}`;
          } else if (scanType === 'Web') {
            detailUrl = `/task-manage/web-detail/${_id}`;
          } else if (scanType === 'Honeypot') {
            detailUrl = `/task-manage/honeypot-detail/${_id}`;
          } else if (scanType === 'OneDay') {
            detailUrl = `/task-manage/oneday-detail/${_id}`;
          } else if (scanType === 'VulDetect') {
            detailUrl = `/task-manage/vul-detect-detail/${_id}`;
          }
          return (
            <div className="task-name-text">
              <Tooltip title={'查看任务详情'}>
                <NavLink className="detail" to={detailUrl} onClick={this.scorllToTop}>
                  {name}
                </NavLink>
              </Tooltip>
              {urgent && <div className="urgent">加急</div>}
            </div>
          );
        }
      },
      {
        title: '检测目标',
        key: 'goal',
        width: 130,
        render: (row = {}) => {
          let { scanType, maxDetectionTaskParams, onedayTaskParams } = row;
          // if (_.get(maxDetectionTaskParams, 'target.description')) {
          //   return _.get(maxDetectionTaskParams, 'target.description');
          // }
          // if (_.get(onedayTaskParams, 'target.description')) {
          //   return _.get(onedayTaskParams, 'target.description');
          // }
          let values;
          if (scanType === 'Zoomeye' || scanType === 'Web' || scanType === 'Honeypot') {
            const queryType = _.get(maxDetectionTaskParams, 'target.queryType');
            if (['custom', 'siteIdList', 'targetGroup'].includes(queryType)) {
              values = _.get(row, 'maxDetectionTaskParams.target.showList', []);
            } else {
              return _.get(maxDetectionTaskParams, 'target.description');
            }
          } else if (scanType === 'VulDetect' || scanType === 'OneDay') {
            const queryType = _.get(onedayTaskParams, 'target.queryType');
            if (['custom', 'siteIdList', 'affectedByTarget', 'targetGroup'].includes(queryType)) {
              values = _.get(row, 'onedayTaskParams.target.showList', []);
            } else {
              return _.get(onedayTaskParams, 'target.description');
            }
          } else {
            const description =
              _.get(row, 'onedayTaskParams.target.description') ||
              _.get(row, 'maxDetectionTaskParams.target.description');
            return description;
          }
          const parsedValues = values.slice(0, 4);
          if (values.length > 4) {
            parsedValues[3] = '...';
          }
          if (!parsedValues.length) {
            parsedValues.push('目标已被删除');
          }
          const goal = (
            <div className="goals">
              {parsedValues.map((value, index) => {
                return (
                  <Tooltip key={index} title={value}>
                    <div className="item">{value}</div>
                  </Tooltip>
                );
              })}
            </div>
          );
          return goal;
        }
      },
      {
        title: '任务类型',
        dataIndex: 'fakeScanType',
        width: 120,
        render: type => {
          return TASK_TYPE_MAP[type] || '-';
        }
      },
      {
        title: '任务状态',
        render: item => {
          let status = _.get(item, 'status');
          if (status === 'paused') {
            return this.getProgress(item);
          }
          let ele;

          let { isRunAt = false, hasRun = true, time } = _.get(item, 'runAt', {});
          if (PROCESSING_TASK_STATES.indexOf(status) !== -1) {
            ele = (
              <span className="status processing">{status === 'stopping' ? '终止中' : '运行'}</span>
            );
          } else if (WAITING_TASK_STATES.indexOf(status) !== -1) {
            if (isRunAt && !hasRun) {
              ele = <span className="status waiting">等待:预计 {time} 开始准备执行</span>;
            } else {
              ele = <span className="status waiting">等待</span>;
            }
          } else {
            ele = <span className="status finished">完成</span>;
          }
          return ele;
        }
      },
      ...hookColumns,
      {
        title: '创建人',
        dataIndex: 'user_oid',
        render: value => {
          return _.get(value, 'nickname', '-');
        }
      },
      {
        title: '操作',
        width: 220,
        className: 'operations-wrapper',
        render: row => {
          const operator = (
            <Operator
              row={row}
              disabled={row.status === 'stopping'}
              status={taskFilter.status}
              setMoreModalType={type => this.setMoreModalType(type, row)}
            />
          );
          return operator;
        }
      }
    ];
    return columns;
  };

  onCancelMoreModal = () => {
    this.setMoreModalType('', null);
  };

  stopTask = task => {
    this.setState({ moreModalLoading: true });
    cancelTask(task)
      .then(() => {
        message.success('成功下发终止任务请求');
        this.setState({
          moreModalType: ''
        });
      })
      .catch(err => {
        message.error(err.message || '下发终止任务请求失败');
      })
      .finally(() => {
        this.setState({ moreModalLoading: false });
      });
  };

  cancelTask = (task, status) => {
    this.setState({ moreModalLoading: true });
    cancelTask(task)
      .then(() => {
        message.success('成功下发取消任务请求');
        this.setState({
          moreModalType: ''
        });
        if (status === 'waiting') {
          this.loadTasks();
        }
      })
      .catch(err => {
        message.error(err.message || '下发取消任务请求失败');
      })
      .finally(() => {
        this.setState({ moreModalLoading: false });
      });
  };

  resumeTask = task => {
    this.setState({ moreModalLoading: true });
    resumeTask(task)
      .then(() => {
        message.success('成功下发启动任务请求');
        this.setState({
          moreModalType: ''
        });
      })
      .catch(err => {
        message.error(err.message || '下发任务请求失败');
      })
      .finally(() => {
        this.setState({ moreModalLoading: false });
      });
  };

  pausedTask = task => {
    this.setState({ moreModalLoading: true });
    stopTask(task)
      .then(() => {
        message.success('成功下发暂停任务请求');
        this.setState({
          moreModalType: ''
        });
      })
      .catch(err => {
        message.error(err.message || '下发暂停任务请求失败');
      })
      .finally(() => {
        this.setState({ moreModalLoading: false });
      });
  };

  restartTask = task => {
    if (!this.props.modules.includes('detection')) {
      return message.info('演示版本不能下发任务，请联系ZoomEye BE团队获取正式版本');
    }
    this.setState({ moreModalLoading: true });
    restartTask(task)
      .then(() => {
        message.success('成功下发复测任务请求');
        this.setState({
          moreModalType: ''
        });
        this.loadTasks();
      })
      .catch(({ type, message: messageString }) => {
        if (type === 'parsed') {
          message.error(messageString);
        } else {
          message.error('下发复测任务请求失败');
        }
      })
      .finally(() => {
        this.setState({ moreModalLoading: false });
      });
  };

  onMoreModalOk = async () => {
    await isClusterModel();
    const { moreModalType, currentTask = {}, selectedRowKeys } = this.state;
    const moreModalOks = {
      stop: () => this.stopTask(currentTask._id),
      cancel: () => this.cancelTask(currentTask._id, currentTask.status),
      delete: () => this.deleteTasks([currentTask._id]),
      batchDelete: () => this.deleteTasks(selectedRowKeys),
      reDetect: () => this.restartTask(currentTask._id),
      resume: () => this.resumeTask(currentTask._id),
      paused: () => this.pausedTask(currentTask._id)
    };
    moreModalOks[moreModalType] && moreModalOks[moreModalType]();
  };

  setMoreModalType = (type, current) => {
    this.setState({
      moreModalType: type,
      currentTask: current
    });
  };

  afterAddZoomeye = () => {
    this.setState(
      {
        zoomeyeModalVisible: false
      },
      this.loadTasks
    );
  };

  affterAddOneday = () => {
    this.setState(
      {
        onedayModalVisible: false
      },
      this.loadTasks
    );
  };

  onBatchDelete = () => {
    this.setState({
      moreModalType: 'batchDelete'
    });
  };

  onSearchChange = e => {
    const taskFilter = _.clone(this.state.taskFilter);
    taskFilter.search = e.target.value;
    this.setState({ taskFilter });
  };

  getRowClassName = record => {
    let isChecked = _.get(record, 'isChecked', true);
    if (!isChecked) {
      return 'table-row-isChecked';
    }
    return '';
  };

  render() {
    const {
      tasks,
      taskFilter,
      totalTasksCount,
      moreModalType,
      zoomeyeModalVisible,
      onedayModalVisible,
      loadingTasks,
      moreModalLoading,
      selectedRowKeys,
      templateIps,
      currentTask
    } = this.state;
    const { modules = [] } = this.props;
    const hasOneDayModule = modules.includes('1day');
    const columns = this.getColumns();

    const pagination = {
      current: taskFilter.page,
      pageSize: taskFilter.pageSize,
      total: totalTasksCount,
      showQuickJumper: true,
      showSizeChanger: true,
      showTotal: num => `共 ${num} 条`,
      size: 'small'
    };

    const emptyData = () => (
      <Empty
        image={EmptyDataImg}
        imageStyle={{
          height: 242
        }}
        description="任务为空，快添加任务，开始资产管理吧"
        style={{ padding: '0 0 68px' }}
      >
        <Button
          type="primary"
          onClick={() =>
            this.props.history.push({
              pathname: '/task-list/add-task',
              state: { type: 'Zoomeye' }
            })
          }
        >
          资产探测
        </Button>
      </Empty>
    );
    const rowSelection = {
      onChange: selectedRowKeys => {
        this.setState({ selectedRowKeys });
      },
      selectedRowKeys
    };

    return (
      <div className="task-manage">
        <div className="title">任务管理</div>
        <div className="operations">
          <div className="left filter-tab">
            <RadioGroup
              value={taskFilter.status}
              onChange={this.wrapOnFilterChange('status', 'target.value')}
            >
              <RadioButton value="waiting">等待</RadioButton>
              <RadioButton value="processing">执行中</RadioButton>
              <RadioButton value="finished">已完成</RadioButton>
            </RadioGroup>
            <div className="task-type-select">
              任务类型
              <Select
                value={taskFilter.scanType}
                onChange={this.wrapOnFilterChange('scanType')}
                getPopupContainer={triggerNode => triggerNode.parentNode}
              >
                <SelectOption key="all">全部</SelectOption>
                <SelectOption key="Zoomeye">资产探测</SelectOption>
                {hasOneDayModule && <SelectOption key="OneDay">1DAY检测</SelectOption>}
                {hasOneDayModule && <SelectOption key="WeakPassword">弱口令</SelectOption>}
                {hasOneDayModule && <SelectOption key="VulDetect">漏洞普查</SelectOption>}
              </Select>
            </div>
          </div>
          <div className="right">
            <Search
              placeholder="请输入任务名称"
              enterButton
              onSearch={this.wrapOnFilterChange('search')}
              onChange={this.onSearchChange}
              value={taskFilter.search}
            />
          </div>
        </div>
        <div className="operations">
          <div className="left">
            <Button type="danger" disabled={!selectedRowKeys.length} onClick={this.onBatchDelete}>
              批量删除
            </Button>
          </div>
        </div>
        <ConfigProvider renderEmpty={emptyData}>
          <Table
            rowKey="_id"
            className="tabel"
            dataSource={tasks}
            columns={columns}
            pagination={pagination}
            rowSelection={rowSelection}
            onChange={this.onTableChange}
            loading={{ spinning: loadingTasks, tip: '加载中' }}
            locale={{
              emptyText: (
                <Empty
                  description={loadingTasks ? ' ' : '暂无数据'}
                  image={Empty.PRESENTED_IMAGE_SIMPLE}
                />
              )
            }}
            scroll={{ x: true, scrollToFirstRowOnChange: true }}
            rowClassName={this.getRowClassName}
            templateIps={templateIps}
          />
        </ConfigProvider>
        <OnedayModal
          visible={onedayModalVisible}
          setModalVisible={this.setAddTaskModalVisible}
          templateIps={templateIps}
          onSuccess={this.affterAddOneday}
        />
        <ZoomeyeModal
          visible={zoomeyeModalVisible}
          onSuccess={this.afterAddZoomeye}
          onVisibleChange={visible => this.setAddTaskModalVisible('zoomeye', visible)}
        />
        <Modal
          maskClosable={false}
          className="tm-more-modal"
          visible={Boolean(moreModalType) && moreModalType !== 'export'}
          title={`${moreTypesMap[moreModalType] || ''}任务`}
          okText="确认"
          cancelText="取消"
          onCancel={this.onCancelMoreModal}
          onOk={this.onMoreModalOk}
          confirmLoading={moreModalLoading}
        >
          {moreTypesMap[moreModalType] === '终止'
            ? '由于中途终止任务的资产数据不完善，所以已探测出的资产不会入库资产表，'
            : ''}
          确定{moreTypesMap[moreModalType] || ''}任务吗?
        </Modal>
        <TaskExportModal
          task={currentTask || {}}
          visible={moreModalType === 'export'}
          onVisibleChange={visible => !visible && this.setMoreModalType('', null)}
        />
      </div>
    );
  }
}

TaskManageList.propTypes = {
  totalUsersCount: PropTypes.number,
  getTasksList: PropTypes.func,
  tasks: PropTypes.array,
  totalTasksCount: PropTypes.number,
  setModalVisible: PropTypes.bool,
  socketIO: PropTypes.object,
  modules: PropTypes.array,
  getServerTime: PropTypes.func,
  history: PropTypes.object
};

const mapStateToProps = state => {
  return {
    socketIO: _.get(state, 'socketIO.socketIO', null),
    modules: _.get(state, 'auth.cert.modules', [])
  };
};

const mapDispatchToProps = dispatch => {
  return {
    ...bindActionCreators(systemActions, dispatch)
  };
};

export default withRouter(
  connect(
    mapStateToProps,
    mapDispatchToProps
  )(TaskManageList)
);
